package com.ruicar.afs.cloud.afscase.risk.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.afscase.approveprev.entity.CaseApprovePrevInfo;
import com.ruicar.afs.cloud.afscase.approvetask.entity.WorkTaskPoolHistory;
import com.ruicar.afs.cloud.afscase.approvetask.service.WorkTaskPoolHistoryService;
import com.ruicar.afs.cloud.afscase.channel.entity.ChannelAffiliatedUnits;
import com.ruicar.afs.cloud.afscase.channel.entity.ChannelBaseInfo;
import com.ruicar.afs.cloud.afscase.channel.entity.ChannelRiskInfo;
import com.ruicar.afs.cloud.afscase.channel.service.ChannelAffiliatedUnitsService;
import com.ruicar.afs.cloud.afscase.channel.service.ChannelBaseInfoService;
import com.ruicar.afs.cloud.afscase.channel.service.ChannelRiskInfoService;
import com.ruicar.afs.cloud.afscase.common.utils.DicUtils;
import com.ruicar.afs.cloud.afscase.infomanagement.entity.*;
import com.ruicar.afs.cloud.afscase.infomanagement.service.*;
import com.ruicar.afs.cloud.afscase.loanapprove.entity.CarInvoiceInfo;
import com.ruicar.afs.cloud.afscase.loanapprove.service.CarInvoiceInfoService;
import com.ruicar.afs.cloud.afscase.processor.enums.NormalSubmitType;
import com.ruicar.afs.cloud.afscase.risk.service.DataQueryService;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinCostDetails;
import com.ruicar.afs.cloud.bizcommon.business.entity.FinFinancingItems;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyDiscountDetailsService;
import com.ruicar.afs.cloud.bizcommon.business.service.ApplyFinancingItemsService;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.*;
import com.ruicar.afs.cloud.components.datadicsync.DicHelper;
import com.ruicar.afs.cloud.components.datadicsync.dto.DicDataDto;
import com.ruicar.afs.cloud.parameter.commom.entity.TsysAddressParam;
import com.ruicar.afs.cloud.parameter.commom.service.TsysAddressParamService;
import com.ruicar.afs.cloud.risk.api.dto.business.*;
import com.ruicar.afs.cloud.risk.api.dto.tortoise.request.TortoiseApplyData;
import com.ruicar.afs.cloud.risk.api.dto.tortoise.request.TortoisePrevApproveData;
import com.ruicar.afs.cloud.risk.api.enums.tortoise.GwtTortoiseScene;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author Peng Jinbo
 * @Date 2020/08/03 17:58
 */
@Service
@AllArgsConstructor
public class DataQueryServiceImpl implements DataQueryService {

    /**
     * Case base info service
     */
    private CaseBaseInfoService caseBaseInfoService;
    /**
     * Case cost info service
     */
    private CaseCostInfoService caseCostInfoService;
    /**
     * Case channel info service
     */
    private CaseChannelInfoService caseChannelInfoService;
    /**
     * Case car info service
     */
    private CaseCarInfoService caseCarInfoService;
    /**
     * Case car style detail service
     */
    private CaseCarStyleDetailService caseCarStyleDetailService;
    /**
     * Case cust info service
     */
    private CaseCustInfoService caseCustInfoService;
    /**
     * Channel affiliated units service
     */
    private ChannelAffiliatedUnitsService channelAffiliatedUnitsService;
    /**
     * Case cust address service
     */
    private CaseCustAddressService caseCustAddressService;
    /**
     * Case cust individual service
     */
    private CaseCustIndividualService caseCustIndividualService;
    /**
     * Case contract info service
     */
    private CaseContractInfoService caseContractInfoService;
    /**
     * Case cust contact service
     */
    private CaseCustContactService caseCustContactService;
    /**
     * Car invoice info service
     */
    private CarInvoiceInfoService carInvoiceInfoService;
    /**
     * Channel base info service
     */
    private ChannelBaseInfoService channelBaseInfoService;
    /**
     * Address param service
     */
    private TsysAddressParamService addressParamService;
    /**
     * Discount details service
     */
    private ApplyDiscountDetailsService discountDetailsService;

    private ApplyFinancingItemsService applyFinancingItemsService;

    private ChannelRiskInfoService channelRiskInfoService;

    private WorkTaskPoolHistoryService workTaskPoolHistoryService;

    /**
     * Author Peng Jinbo
     * Query main apply main info
     *
     * @param applyNo apply no
     * @return the apply main info
     */
    @Override
    public ApplyMainInfo queryMain(String applyNo) {
        // 案件主表
        CaseBaseInfo casebaseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                        .eq(CaseBaseInfo::getApplyNo, applyNo)
        );
        // 渠道
        CaseChannelInfo caseChannelInfo = caseChannelInfoService.getOne(
                Wrappers.<CaseChannelInfo>lambdaQuery()
                        .eq(CaseChannelInfo::getApplyNo, applyNo)
        );

        // 最新审批历史
        WorkTaskPoolHistory poolHistory = workTaskPoolHistoryService.list(
                Wrappers.<WorkTaskPoolHistory>lambdaQuery()
                    .eq(WorkTaskPoolHistory::getProcessType,ProcessTypeEnum.GENERA_APPROVE.getCode())
                    .eq(WorkTaskPoolHistory::getApplyNo,applyNo)
                    .orderByDesc(WorkTaskPoolHistory::getCreateTime)
        ).stream().findFirst().orElse(new WorkTaskPoolHistory());
        String approveStatusName = null;
        if(StrUtil.isNotBlank(poolHistory.getApproveSuggest())){
            NormalSubmitType submitType = (NormalSubmitType) AfsEnumUtil.getEnum(poolHistory.getApproveSuggest(),NormalSubmitType.class);
            if(Objects.nonNull(submitType)){
                approveStatusName = AfsEnumUtil.desc(submitType);
            }
        }
        return ApplyMainInfo.builder()
                .applyNo(applyNo)
                .firstSubmitDate(casebaseInfo.getPassFirstDate())
                .approveAgreeDate(casebaseInfo.getProcessorEndTime())
                .rejectReason(casebaseInfo.getRejectReason())
                .loanPeriod(obj2Str(casebaseInfo.getLoanTermsRepeat()))
                .sellStaffName(caseChannelInfo.getSaleAdvisor())
                .sellStaffPhone(caseChannelInfo.getSalePhone())
                .businessStatusIn(casebaseInfo.getBusinessStateIn())
                .dealerSubmitMessage(casebaseInfo.getRemarks())
                .businessType(casebaseInfo.getBusinessType())
                .affiliatedMode(StrUtil.isBlank(obj2Str(casebaseInfo.getAffiliatedWay()))
                        || AffiliatedWayEnum.NO.getCode().equals(obj2Str(casebaseInfo.getAffiliatedWay()))
                        ? WhetherEnum.NO.getCode() : WhetherEnum.YES.getCode())
                .onlineCar(OperateWayEnum.NETWORK_CAR.getCode().equalsIgnoreCase(casebaseInfo.getOperateWay())
                        ? WhetherEnum.YES.getCode()
                        : WhetherEnum.NO.getCode())
                .remoteSign(casebaseInfo.getAutomaticTag())
                .conditionMark(casebaseInfo.getConditionMark())
                .approveStatus(poolHistory.getApproveSuggest())
                .approveStatusName(approveStatusName)
                .dealerName(caseChannelInfo.getDealerName())
                .carNature(casebaseInfo.getCarNature())
                .mainId(casebaseInfo.getId().toString())
                .build();
    }

    /**
     * Author Peng Jinbo
     * Query cost apply cost info
     *
     * @param applyNo apply no
     * @return the apply cost info
     */
    @Override
    public ApplyCostInfo queryCost(String applyNo) {
        // 案件主表
        CaseBaseInfo casebaseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                        .eq(CaseBaseInfo::getApplyNo, applyNo)
        );
        // 费用信息 = 车款 + 附加贷
        List<FinCostDetails> caseCostInfos = caseCostInfoService.list(
                Wrappers.<FinCostDetails>lambdaQuery()
                        .eq(FinCostDetails::getApplyNo, applyNo)
        );
        BigDecimal contractAmt = BigDecimal.ZERO;   // 合同款
        BigDecimal monthRepay = BigDecimal.ZERO;    // 月供
        BigDecimal tailRepay = BigDecimal.ZERO;     // 尾付
        BigDecimal loanAmt = BigDecimal.ZERO;       // 贷款总额
        BigDecimal interestAmt = BigDecimal.ZERO;   // 利息总额
        BigDecimal discountAmt = BigDecimal.ZERO;   // 贴息总额
        BigDecimal downPayAmt = BigDecimal.ZERO;    // 首付
        for (FinCostDetails cost : caseCostInfos) {
            contractAmt = contractAmt.add(Convert.toBigDecimal(cost.getContractAmt(),BigDecimal.ZERO));
            monthRepay = monthRepay.add(Convert.toBigDecimal(cost.getMonthPayAmt(),BigDecimal.ZERO));
            tailRepay = tailRepay.add(Convert.toBigDecimal(cost.getTailPayAmt(),BigDecimal.ZERO));
            loanAmt = loanAmt.add(Convert.toBigDecimal(cost.getLoanAmt(),BigDecimal.ZERO));
            interestAmt = interestAmt.add(Convert.toBigDecimal(cost.getTotalInterest(),BigDecimal.ZERO));
            discountAmt = discountAmt.add(Convert.toBigDecimal(cost.getDiscountAmt(),BigDecimal.ZERO));
            downPayAmt = downPayAmt.add(Convert.toBigDecimal(cost.getDownPayAmt(),BigDecimal.ZERO));
        }

        // 车款
        FinCostDetails carCost = caseCostInfos.stream().filter(cost -> CostTypeEnum.CARAMT.getCode().equals(cost.getCostType())).findFirst().orElse(new FinCostDetails());
        contractAmt = contractAmt.add(Convert.toBigDecimal(carCost.getAddAmt(),BigDecimal.ZERO));

        // 附加贷
        List<FinFinancingItems> caseAppendCostList = applyFinancingItemsService.list(
                Wrappers.<FinFinancingItems>lambdaQuery()
                    .eq(FinFinancingItems::getApplyNo,applyNo)
                    .isNull(FinFinancingItems::getUpperId)
        );
        List<ApplyAppendProductInfo> appendCostList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(caseAppendCostList)) {
            for (FinFinancingItems appendCost : caseAppendCostList) {
                // 过滤金额小于0数据
                if(Convert.toBigDecimal(appendCost.getFinanceItemAmt(),BigDecimal.ZERO).compareTo(BigDecimal.ZERO) > 0) {
                    appendCostList.add(ApplyAppendProductInfo.builder()
                            .appendProductName(appendCost.getFinanceItemName())
                            .appendProductPrice(appendCost.getFinanceItemAmt())
                            .build());
                }
            }
        }
/*        FinDiscountDetails discountCost = discountDetailsService.getOne(
                Wrappers.<FinDiscountDetails>lambdaQuery()
                    .eq(FinDiscountDetails::getCostId,carCost.getId() + "")
        );*/

        return ApplyCostInfo.builder()
                .applyNo(applyNo)
                .tailPayScale(carCost.getTailPayScale())
                .customerRate(carCost.getCustRate())
                .contractAmount(contractAmt)
                .carPrice(carCost.getContractAmt())
                .downPayScale(carCost.getDownPayScale())
                .downPayAmount(downPayAmt)
                .loanAmount(loanAmt)
                .tailPayAmount(tailRepay)
                .periodRepayAmount(monthRepay)
                .interestAmount(interestAmt)
                .product(carCost.getProductId())
                .productName(carCost.getProductName())
                .repayFrequency("0") // 还款频率 默认月付
                .vendorDiscountScale(null) // TODO 厂商贴息比例
                .vendorDiscountAmt(null) // TODO 厂商贴息金额
                .discountScale(null) // TODO 贴息比例
                .discountAmt(carCost.getDiscountAmt())
                .appendProductInfoList(appendCostList)
                .build();
    }

    /**
     * Author Peng Jinbo
     * Query contract apply contract info
     *
     * @param applyNo apply no
     * @return the apply contract info
     */
    @Override
    public ApplyContractInfo queryContract(String applyNo) {
        // 合同信息
        List<CaseContractInfo> caseContractInfoList = caseContractInfoService.list(
                Wrappers.<CaseContractInfo>lambdaQuery()
                        .eq(CaseContractInfo::getApplyNo, applyNo)
        );
        // 暂不考虑多车多合同情况
        CaseContractInfo caseContractInfo = CollectionUtil.isNotEmpty(caseContractInfoList) ? caseContractInfoList.get(0) : new CaseContractInfo();
        // 车辆发票信息表
        List<CarInvoiceInfo> caseCarInvoiceInfoList = carInvoiceInfoService.list(
                Wrappers.<CarInvoiceInfo>lambdaQuery()
                        .eq(CarInvoiceInfo::getApplyNo, applyNo)
        );
        CarInvoiceInfo caseCarInvoiceInfo = CollectionUtil.isNotEmpty(caseContractInfoList) ? caseCarInvoiceInfoList.get(0) : new CarInvoiceInfo();
        Map<String, List<DicDataDto>> contractStatusDicMap = DicHelper.getDicMaps("conApplyStatus");
        return ApplyContractInfo.builder()
                .applyNo(applyNo)
                .contractNo(caseContractInfo.getContractNo())
                .contractInnerStatus(caseContractInfo.getApplyStatus())
                .contractInnerStatusName(DicUtils.translate(caseContractInfo.getApplyStatus(),contractStatusDicMap))
                .ticketUnitName(caseCarInvoiceInfo.getMakeInvoiceUnit()) // 开票单位
                .build();
    }

    /**
     * Author Peng Jinbo
     * Query cars list
     *
     * @param applyNo apply no
     * @return the list
     */
    @Override
    public List<ApplyCarInfo> queryCars(String applyNo) {
        // 案件主表
        CaseBaseInfo casebaseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                        .eq(CaseBaseInfo::getApplyNo, applyNo)
        );
        // 车辆信息
        List<CaseCarInfo> caseCarInfoList = caseCarInfoService.list(
                Wrappers.<CaseCarInfo>lambdaQuery()
                        .eq(CaseCarInfo::getApplyNo, applyNo)
        );

        List<ApplyCarInfo> carInfoList = new ArrayList<>();
        for (CaseCarInfo caseCarInfo : caseCarInfoList) {
            CaseCarStyleDetail styleDetail = caseCarStyleDetailService.getOne(
                    Wrappers.<CaseCarStyleDetail>lambdaQuery()
                            .eq(CaseCarStyleDetail::getCarId, caseCarInfo.getId().toString())
            );
            String carVendorAddress = getProvOrCity(caseCarInfo.getCarDealerProvince()) + getProvOrCity(caseCarInfo.getCarDealerCity());
            carInfoList.add(ApplyCarInfo.builder()
                    .greenPower(styleDetail.getIsGreen())
                    .applyNo(applyNo)
                    .newCarSalePrice(caseCarInfo.getGuidePrice())
                    .carVendorName(caseCarInfo.getCarDealerName())
                    .carVendorPhone(caseCarInfo.getCarDealerPhone())
                    .carVendorAddress(carVendorAddress)
                    .licensePlate(caseCarInfo.getLicensePlate())
                    .secondDealCarPrice(caseCarInfo.getSecondSalePrice())
                    .thirdProspectPrice(caseCarInfo.getEvaluatingPrice())
                    .firstRegisterDate(caseCarInfo.getFirstLandingDate())
                    .carModel(caseCarInfo.getCarBodyClass())
                    .brand(Convert.toStr(caseCarInfo.getBrandCode(),""))
                    .brandName(caseCarInfo.getBrandName())
                    .vehicleType(casebaseInfo.getCarType())
                    .vehicleModel(Convert.toStr(caseCarInfo.getModelCode(),""))
                    .vehicleModelName(caseCarInfo.getModelName())
                    .vin(caseCarInfo.getCarVin())
                    .engineNo(caseCarInfo.getEngineNo())
                    .registerProvince(caseCarInfo.getRegistProvince())
                    .registerProvinceName(getProvOrCity(caseCarInfo.getRegistProvince()))
                    .registerCity(caseCarInfo.getRegistCity())
                    .registerCityName(getProvOrCity(caseCarInfo.getRegistCity()))
                    .buyProvince(caseCarInfo.getPurchaseProvince())
                    .buyProvinceName(getProvOrCity(caseCarInfo.getPurchaseProvince()))
                    .buyCity(caseCarInfo.getPurchaseCity())
                    .buyCityName(getProvOrCity(caseCarInfo.getPurchaseCity()))
                    .buyPurpose(casebaseInfo.getCarPurpose())
                    .plateProvince(caseCarInfo.getLicenseProvince())
                    .plateProvinceName(getProvOrCity(caseCarInfo.getLicenseProvince()))
                    .plateCity(caseCarInfo.getLicenseCity())
                    .plateCityName(getProvOrCity(caseCarInfo.getLicenseCity()))
                    .assetCode("") // 资产编码
                    .optionPrice(BigDecimal.ZERO) // 选装价格
                    .guidePrice(caseCarInfo.getGuidePrice()) //
                    .carStyle(Convert.toStr(caseCarInfo.getStyleCode(),""))
                    .carStyleName(caseCarInfo.getStyleName())
                    .ownerIdCard(caseCarInfo.getBelongsCertNo())
                    .ownerCompanyName(caseCarInfo.getCarBelongs())
                    .registration(StrUtil.isNotBlank(caseCarInfo.getLicenseProvince()) ? WhetherEnum.YES.getCode() : WhetherEnum.NO.getCode())
                    .makeDate(caseCarInfo.getVehicleMadeDate())
                    .transferTimes(caseCarInfo.getTransNums())
                    .mileage(caseCarInfo.getMileage())
                    .plateCarTicketDate(caseCarInfo.getInvoiceTime())
                    .build());
        }
        return carInfoList;
    }

    /**
     * Author Peng Jinbo
     * Query affiliated apply affiliated info
     *
     * @param applyNo apply no
     * @return the apply affiliated info
     */
    @Override
    public ApplyAffiliatedInfo queryAffiliated(String applyNo) {
        // 车辆信息
        CaseCarInfo carInfo = caseCarInfoService.list(
                Wrappers.<CaseCarInfo>lambdaQuery()
                        .eq(CaseCarInfo::getApplyNo, applyNo)
        ).stream().findFirst().orElse(new CaseCarInfo());
        ChannelAffiliatedUnits affiliatedUnit =
                Optional.ofNullable(channelAffiliatedUnitsService.getById(carInfo.getAffCompanyId()))
                .orElse(new ChannelAffiliatedUnits());
        affiliatedUnit = Objects.nonNull(affiliatedUnit) ? affiliatedUnit : new ChannelAffiliatedUnits();
        // 案件主表
        CaseBaseInfo casebaseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                        .eq(CaseBaseInfo::getApplyNo, applyNo)
        );
        String affiliatedUnitLegalName = AffiliatedWayEnum.PERSONAL_AFFILIATED.getCode().equals(casebaseInfo.getAffiliatedWay())
                ? ""
                : affiliatedUnit.getLegalPersonName();
        String affiliatedUnitLegalPhone = AffiliatedWayEnum.PERSONAL_AFFILIATED.getCode().equals(casebaseInfo.getAffiliatedWay())
                ? ""
                : affiliatedUnit.getLegalPersonTel();
        String affiliatedCompanyName = AffiliatedWayEnum.PERSONAL_AFFILIATED.getCode().equals(casebaseInfo.getAffiliatedWay())
                ? carInfo.getIndBusinessName()
                : affiliatedUnit.getAffiliatedName();
        return ApplyAffiliatedInfo.builder()
                .applyNo(applyNo)
                .legalPersonName(affiliatedUnitLegalName)
                .legalPersonPhone(affiliatedUnitLegalPhone)
                .status(AffiiationEnum.START.getCode().equals(affiliatedUnit.getStatus())
                        ? WhetherEnum.YES.getCode()
                        : WhetherEnum.NO.getCode())
                .registerDate(affiliatedUnit.getRegisteredTime())
                .affiliatedMode(casebaseInfo.getAffiliatedWay())
                .companyName(affiliatedCompanyName)
                .companyProvince(affiliatedUnit.getRegisteredProvince())
                .companyProvinceName(getProvOrCity(affiliatedUnit.getRegisteredProvince()))
                .companyCity(affiliatedUnit.getRegisteredCity())
                .companyCityName(getProvOrCity(affiliatedUnit.getRegisteredCity()))
                .companyPhone(affiliatedUnit.getLegalPersonTel())
                .build();
    }

    /**
     * Author Peng Jinbo
     * Query contacts list
     *
     * @param applyNo apply no
     * @return the list
     */
    @Override
    public List<ApplyContactInfo> queryContacts(String applyNo) {
        // 联系人
        List<CaseCustContact> caseContactList = caseCustContactService.list(
                Wrappers.<CaseCustContact>lambdaQuery()
                        .eq(CaseCustContact::getApplyNo, applyNo)
        );
        // 联系人信息
        List<ApplyContactInfo> contactInfoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(caseContactList)) {
            for (CaseCustContact caseContact : caseContactList) {
                contactInfoList.add(ApplyContactInfo.builder()
                        .userCode(caseContact.getId().toString())
                        .applyNo(applyNo)
                        .cardType(caseContact.getCertType())
                        .idCard(caseContact.getCertNo())
                        .name(caseContact.getCustName())
                        .phone(caseContact.getTelPhone())
                        .companyName(caseContact.getCompanyName())
                        .companyPhone(caseContact.getCompanyPhone())
                        .liveAddress(caseContact.getDetailAddress())
                        .relationShip(caseContact.getCustRelation())
                        .monthIncome(caseContact.getMonthlyIncome())
                        .build());
            }
        }
        return contactInfoList;
    }

    /**
     * Author Peng Jinbo
     * Query dealer apply dealer info
     *
     * @param applyNo apply no
     * @return the apply dealer info
     */
    @Override
    public ApplyDealerInfo queryDealer(String applyNo) {
        CaseBaseInfo caseBaseInfo = caseBaseInfoService.getOne(
                Wrappers.<CaseBaseInfo>lambdaQuery()
                    .eq(CaseBaseInfo::getApplyNo,applyNo)
        );
        // 渠道
        CaseChannelInfo caseChannelInfo = caseChannelInfoService.getOne(
                Wrappers.<CaseChannelInfo>lambdaQuery()
                        .eq(CaseChannelInfo::getApplyNo, applyNo)
        );
        ChannelBaseInfo channelBaseInfo = channelBaseInfoService.getOne(
                Wrappers.<ChannelBaseInfo>lambdaQuery()
                        .eq(ChannelBaseInfo::getChannelCode, caseChannelInfo.getDealerNo())
        );

        ChannelRiskInfo channelRiskInfo = Optional.ofNullable(channelRiskInfoService.getOne(
                Wrappers.<ChannelRiskInfo>lambdaQuery()
                    .eq(ChannelRiskInfo::getChannelId,channelBaseInfo.getChannelId())
                    .eq(ChannelRiskInfo::getBusinessType,caseBaseInfo.getBusinessType())
        )).orElse(new ChannelRiskInfo());

        return ApplyDealerInfo.builder()
                .applyNo(applyNo)
                .dealerName(caseChannelInfo.getDealerName())
                .province(channelBaseInfo.getChannelProvince())
                .provinceName(getProvOrCity(channelBaseInfo.getChannelProvince()))
                .city(channelBaseInfo.getChannelCity())
                .cityName(getProvOrCity(channelBaseInfo.getChannelCity()))
                .startWorkDate(channelBaseInfo.getRegistrationDate())
                .unifiedSocialCreditCode(channelBaseInfo.getSocUniCrtCode())
                .dealerLevel(channelRiskInfo.getChannelGrade())
                .channelBelong(channelBaseInfo.getChannelBelong())
                .direct(StrUtil.equals(channelBaseInfo.getChannelBelong(), AfsEnumUtil.key(ChannelBelongEnum.DIRECT))
                        ? WhetherEnum.YES.getCode() : WhetherEnum.NO.getCode())
                .build();
    }

    /**
     * Author Peng Jinbo
     * Query duties list
     *
     * @param applyNo apply no
     * @return the list
     */
    @Override
    public List<ApplyDutyPersonInfo> queryDuties(String applyNo) {
        // 责任人 = 主借人、共借人、担保人
        List<CaseCustInfo> caseCustInfoList = caseCustInfoService.list(
                Wrappers.<CaseCustInfo>lambdaQuery()
                        .eq(CaseCustInfo::getApplyNo, applyNo)
        );
        // 责任人信息(主借人，共借人，担保人)
        List<ApplyDutyPersonInfo> dutyPersonInfoList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(caseCustInfoList)) {
            for (CaseCustInfo customer : caseCustInfoList) {
                List<ApplyDutyPersonAddressInfo> dutyAddressList = new ArrayList<>();
                CaseCustIndividual customerDetail = caseCustIndividualService.getOne(
                        Wrappers.<CaseCustIndividual>lambdaQuery()
                                .eq(CaseCustIndividual::getCustId, customer.getId())
                );
                List<CaseCustAddress> addresses = caseCustAddressService.list(
                        Wrappers.<CaseCustAddress>lambdaQuery()
                                .eq(CaseCustAddress::getCustId, customer.getId())
                );
                if (CollectionUtil.isNotEmpty(addresses)) {
                    for (CaseCustAddress address : addresses) {
                        if (AfsEnumUtil.key(AddressTypeEnum.CENSUS).equals(address.getAddressType())) {
                            continue;
                        }
                        dutyAddressList.add(ApplyDutyPersonAddressInfo.builder()
                                .applyNo(applyNo)
                                .addressDetail(address.getDetailAddress())
                                .postCode(address.getPostalCode())
                                .currentAddressLiveDate(address.getHouseStartDate())
                                .houseType(address.getHouseType())
                                .addressType(address.getAddressType())
                                .addressProvince(address.getProvince())
                                .addressProvinceName(getProvOrCity(address.getProvince()))
                                .addressCity(address.getCity())
                                .addressCityName(getProvOrCity(address.getCity()))
                                .build());
                    }
                }
                Long betweenMonth = DateUtil.betweenMonth(customerDetail.getBirthday(), new Date(), true);

                dutyPersonInfoList.add(ApplyDutyPersonInfo.builder()
                        .userCode(customer.getId().toString())
                        .dutyPersonType(customer.getCustRole())
                        .applyNo(applyNo)
                        .cardType(customer.getCertType())
                        .dutyPersonType(customer.getCustRole())
                        .name(customer.getCustName())
                        .phone(customer.getTelPhone())
                        .idCard(customer.getCertNo())
                        .idCardEndDate(customer.getCertEndDate())
                        .birthday(customerDetail.getBirthday())
                        .sex(customerDetail.getSex())
                        .nationality(customerDetail.getNationality())
                        .marryStatus(customerDetail.getMaritalStatus())
                        .education(customerDetail.getHighestEducation())
                        .ageOfYear(customerDetail.getAge())
                        .ageOfMonth(obj2Str(betweenMonth))
                        .outsidePhone(null)
                        .selfMonthIncome(customerDetail.getMonthlyIncome())
                        .familyMonthIncome(Convert.toBigDecimal(customerDetail.getOtherIncome(),BigDecimal.ZERO))
                        .monthRepay(BigDecimal.ZERO) // 每月还款额
                        .familyMonthUsed(Convert.toBigDecimal(customerDetail.getMonthlySpend(),BigDecimal.ZERO))
                        .unRepayAmount(Convert.toBigDecimal(customerDetail.getOutstandingLoan(),BigDecimal.ZERO))
                        .companyName(customerDetail.getUnitName())
                        .companyPhone(customerDetail.getUnitTelPhone())
                        .industryType(customerDetail.getIndustryType())
                        .employeeType(customerDetail.getEmployeeType())
                        .jobType(customerDetail.getProfessionalType())
                        .jobPosition(customerDetail.getPosition())
                        .workingLimit(customerDetail.getWorkAge())
                        .driverLicense(customerDetail.getDrivingType())
                        .recordNo(customerDetail.getDrivingLicenceNo())
                        .relationship(customer.getCustRelation())
                        .dutyPersonAddressInfos(dutyAddressList)
                        .build());
            }
        }
        return dutyPersonInfoList;
    }

    /**
     * Author Peng Jinbo
     * Query customer apply duty person info
     *
     * @param applyNo apply no
     * @return the apply duty person info
     */
    @Override
    public ApplyDutyPersonInfo queryCustomer(String applyNo) {
        CaseCustInfo customer = caseCustInfoService.getOne(
                Wrappers.<CaseCustInfo>lambdaQuery()
                        .eq(CaseCustInfo::getApplyNo, applyNo)
                        .eq(CaseCustInfo::getCustRole, CustRoleEnum.MIANCUST.getCode())
        );
        CaseCustIndividual customerDetail = caseCustIndividualService.getOne(
                Wrappers.<CaseCustIndividual>lambdaQuery()
                        .eq(CaseCustIndividual::getCustId, customer.getId())
        );
        return ApplyDutyPersonInfo.builder()
                .name(customer.getCustName())
                .phone(customer.getTelPhone())
                .birthday(customerDetail.getBirthday())
                .idCardEndDate(customer.getCertEndDate())
                .idCard(customer.getCertNo())
                .cardType(customer.getCertType())
                .sex(customerDetail.getSex())
                .build();
    }

    /**
     * Author Peng Jinbo
     * Query prev tortoise prev approve data
     *
     * @param prevInfo prev info
     * @return the tortoise prev approve data
     */
    @Override
    public TortoisePrevApproveData queryPrev(CaseApprovePrevInfo prevInfo) {
        ChannelBaseInfo channelBaseInfo = Optional.ofNullable(
                channelBaseInfoService.getById(prevInfo.getChannelCode())
        ).orElse(new ChannelBaseInfo());

        ApplyDutyPersonInfo dutyPersonInfo = ApplyDutyPersonInfo.builder()
                .name(prevInfo.getCustName())
                .phone(prevInfo.getTelPhone())
                .sex(prevInfo.getSex())
                .birthday(prevInfo.getBirthday())
                .idCardEndDate(prevInfo.getCertEndDate())
                .idCard(prevInfo.getCertNo())
                .cardType(prevInfo.getCertType())
                .applyNo(prevInfo.getApplyNo())
                .build();

        ApplyMainInfo mainInfo = ApplyMainInfo.builder()
                .businessType(prevInfo.getBusinessType())
                .mainId(prevInfo.getId().toString())
                .applyNo(prevInfo.getApplyNo())
                .sellStaffName(prevInfo.getSellerRealName())
                .sellStaffPhone(prevInfo.getSellerPhone())
                .dealerName(prevInfo.getChannelName())
                .build();

        ApplyDealerInfo dealerInfo = ApplyDealerInfo.builder()
                .dealerName(prevInfo.getChannelName())
                .province(channelBaseInfo.getChannelProvince())
                .provinceName(getProvOrCity(channelBaseInfo.getChannelProvince()))
                .city(channelBaseInfo.getChannelCity())
                .cityName(getProvOrCity(channelBaseInfo.getChannelCity()))
                .startWorkDate(channelBaseInfo.getRegistrationDate())
                .build();

        TortoisePrevApproveData prevApproveData = TortoisePrevApproveData.builder()
                .customerInfo(dutyPersonInfo)
                .mainInfo(mainInfo)
                .dealerInfo(dealerInfo)
                .build();

        prevApproveData.setMainId(prevInfo.getId().toString());
        prevApproveData.setScene(GwtTortoiseScene.PREV_APPROVE);
        prevApproveData.setApplyNo(prevInfo.getApplyNo());
        return prevApproveData;
    }

    /**
     * @param applyNo apply no
     * @return the apply data
     * @Author Peng Jinbo Gets apply data *
     */
    public TortoiseApplyData getApplyData(String applyNo) {

        // 申请主要信息
        ApplyMainInfo mainInfo = this.queryMain(applyNo);
        // 费用信息
        ApplyCostInfo costInfo = this.queryCost(applyNo);
        // 合同信息
        ApplyContractInfo contractInfo = this.queryContract(applyNo);
        // 车辆信息
        List<ApplyCarInfo> carInfoList = this.queryCars(applyNo);
        // 挂靠单位信息
        ApplyAffiliatedInfo affiliatedInfo = this.queryAffiliated(applyNo);
        // 联系人信息
        List<ApplyContactInfo> contactInfoList = this.queryContacts(applyNo);
        // 经销商信息
        ApplyDealerInfo dealerInfo = this.queryDealer(applyNo);
        // 责任人信息(主借人，共借人，担保人)
        List<ApplyDutyPersonInfo> dutyPersonInfoList = this.queryDuties(applyNo);

        for (ApplyCarInfo applyCarInfo : carInfoList) {
            if (StrUtil.isBlank(mainInfo.getGreenEnergy())) {
                mainInfo.setGreenEnergy(applyCarInfo.getGreenPower());
            }
        }

        TortoiseApplyData queryBean = TortoiseApplyData.builder()
                .applyMainInfo(mainInfo)
                .applyCostInfo(costInfo)
                .applyContractInfo(contractInfo)
                .applyContactInfoList(contactInfoList)
                .applyDealerInfo(dealerInfo)
                .applyDutyPersonInfoList(dutyPersonInfoList)
                .applyCarInfoList(carInfoList)
                .applyAffiliatedInfo(affiliatedInfo)
                .build();
        queryBean.setMainId(mainInfo.getMainId());
        queryBean.setScene(GwtTortoiseScene.NORMAL_APPLY);
        queryBean.setApplyNo(applyNo);
        return queryBean;
    }


    /**
     * Author Peng Jinbo
     * Obj 2 str string
     *
     * @param obj obj
     * @return the string
     */
    private String obj2Str(Object obj) {
        return obj instanceof Date ? DateUtil.format(((Date) obj), "yyyy-MM-dd HH:mm:ss") : Convert.toStr(obj, "");
    }

    /**
     * @param val val
     * @return the prov or city
     * @Author Peng Jinbo Gets prov or city *
     */
    public String getProvOrCity(String val) {
        TsysAddressParam addressParam = addressParamService.getProvinceOrCtiy(val);
        return Objects.nonNull(addressParam) ? addressParam.getLabel() : "";
    }
}
